import openai
import time
import playsound
import azure.cognitiveservices.speech as speechsdk

openai.api_key = 'your-key'

# 创建语音合成器
speech_config = speechsdk.SpeechConfig('your-key', 'eastasia')
speech_config.speech_recognition_language = "zh-CN"
# The language of the voice that speaks.
speech_config.speech_synthesis_voice_name = 'zh-CN-XiaoxiaoNeural'

audio_config = speechsdk.audio.AudioConfig(use_default_microphone=True)
audio_out_config = speechsdk.audio.AudioOutputConfig(use_default_speaker=True)
# 语言识别器
speech_recognizer = speechsdk.SpeechRecognizer(speech_config=speech_config, audio_config=audio_config)
# 语言合成
speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=audio_out_config)


# 将文本输出到默认麦克风
def speak(text):
    speech_synthesis_result = speech_synthesizer.speak_text_async(text).get()

    if speech_synthesis_result.reason == speechsdk.ResultReason.Canceled:
        cancellation_details = speech_synthesis_result.cancellation_details
        print("Speech synthesis canceled: {}".format(cancellation_details.reason))
        if cancellation_details.reason == speechsdk.CancellationReason.Error:
            if cancellation_details.error_details:
                print("Error details: {}".format(cancellation_details.error_details))
                print("Did you set the speech resource key and region values?")


# 提问
def askQuestion(question):
    try:
        print('gpt response...')
        response = openai.Completion.create(
            model="text-davinci-003",
            prompt=question,
            temperature=0,
            max_tokens=4000,
            top_p=1,
            frequency_penalty=0.0,
            presence_penalty=0.6,
            stop=None
        )
        message = response.choices[0].text
        print(message)
        speak(message)
    except:
        print('正在重试')
        speak("与服务器连接超时啦，刘宝正在快马加鞭重试中")
        time.sleep(1)
        askQuestion(question)


# 获取麦克风输入
def recognize_from_microphone():
    speech_recognition_result = speech_recognizer.recognize_once_async().get()

    if speech_recognition_result.reason == speechsdk.ResultReason.RecognizedSpeech:
        print("microphone_inpt text: {}".format(speech_recognition_result.text))
        return speech_recognition_result.text
    elif speech_recognition_result.reason == speechsdk.ResultReason.NoMatch:
        print("No speech could be recognized: {}".format(speech_recognition_result.no_match_details))
    elif speech_recognition_result.reason == speechsdk.ResultReason.Canceled:
        cancellation_details = speech_recognition_result.cancellation_details
        print("Speech Recognition canceled: {}".format(cancellation_details.reason))
        if cancellation_details.reason == speechsdk.CancellationReason.Error:
            print("Error details: {}".format(cancellation_details.error_details))
            print("Did you set the speech resource key and region values?")


# 开始监听microphone输入
def start_listen_microphone():
    welcome()
    while True:
        print("Listening microphone...")
        microphone_inpt = recognize_from_microphone()
        if (microphone_inpt is None) or (len(microphone_inpt)) == 0:
            continue
        askQuestion(microphone_inpt)


# 欢迎词
def welcome():
    speak("我是刘宝，主人请吩咐！")


# 麦克风本地识别关键字
def speech_recognize_keyword_locally_from_microphone():
    # Creates an instance of a keyword recognition model. Update this to
    # point to the location of your keyword recognition model.
    model = speechsdk.KeywordRecognitionModel("./keyword/nhnb.table")

    # 识别关键字
    keyword = "你好刘宝"

    # 使用默认麦克风设备创建本地关键字识别器进行输入。
    keyword_recognizer = speechsdk.KeywordRecognizer()

    done = False

    def recognized_cb(evt):
        # 仅识别关键字短语。结果不能为“NoMatch”，并且没有超时。
        # 识别器将一直运行，直到检测到关键字短语或取消识别
        # （通过 stop_recognition_async（） 或由于输入文件或流的结束）
        result = evt.result
        if result.reason == speechsdk.ResultReason.RecognizedKeyword:
            print("RECOGNIZED KEYWORD: {}".format(result.text))
        nonlocal done
        done = True

    def canceled_cb(evt):
        result = evt.result
        if result.reason == speechsdk.ResultReason.Canceled:
            print('CANCELED: {}'.format(result.cancellation_details.reason))
        nonlocal done
        done = True

    # Connect callbacks to the events fired by the keyword recognizer.
    keyword_recognizer.recognized.connect(recognized_cb)
    keyword_recognizer.canceled.connect(canceled_cb)

    # 关键字识别
    result_future = keyword_recognizer.recognize_once_async(model)
    print('Say something starting with "{}" followed by whatever you want...'.format(keyword))
    result = result_future.get()

    # 读取结果音频（包括关键字）。
    if result.reason == speechsdk.ResultReason.RecognizedKeyword:
        time.sleep(2)  # give some time so the stream is filled
        result_stream = speechsdk.AudioDataStream(result)
        result_stream.detach_input()  # stop any more data from input getting to the stream
        start_listen_microphone()

    # If active keyword recognition needs to be stopped before results, it can be done with
    #
    stop_future = keyword_recognizer.stop_recognition_async()
    print('Stopping...')
    stopped = stop_future.get()


speech_recognize_keyword_locally_from_microphone()
